package com.fayou.aop.aspectaopdemo.aspect;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import java.lang.reflect.Proxy;

@Aspect
@Component
public class IntroductionAop {

    Logger logger = LoggerFactory.getLogger(IntroductionAop.class);


    /**
     * 第一个*,public
     * +包名，如果包含子包是..,如果集体到某个包里面的所有类是.
     * 第二个*,类名
     * 第三个*,方法名
     * （..）表示任意参数
     */
    @Pointcut("execution(* com.fayou.aop.aspectaopdemo.service..*.*(..))")
    public void pointCut() {
    }

    @Pointcut("execution(* com.fayou.aop.aspectaopdemo.service..*.query*(..))")
    public void pointCutQuery() {
    }

    /**
     * within作用在类上，增强某个类的所有方法
     */
    @Pointcut("within(com.fayou.aop.aspectaopdemo.service..*)")
    public void pointWithin() {
    }

    /**
     * args参数符合表达式的方法增强
     */
    @Pointcut("within(com.fayou.aop.aspectaopdemo.service..*)&&args(java.lang.Integer)")
    public void pointArgs() {
    }

    /**
     * 增强范围：所有的代理类(aop对象)并且 instanceof com.fayou.cloud.service.PaymentService
     * jdk public final class $Proxy0 extends Proxy implements HelloInterface
     * cglib
     */
    @Pointcut("this(com.fayou.cloud.service.PaymentService)")
//    @Pointcut("this(com.fayou.aop.aspectaopdemo.service.impl.PaymentServiceImpl)")
    public void pointThis() {
    }

    @Pointcut("target(com.fayou.cloud.service.PaymentService)")
//    @Pointcut("this(com.fayou.aop.aspectaopdemo.service.impl.PaymentServiceImpl)")
    public void pointTarget() {
    }

    //    @Before("pointCut()")
//    public void doAccessCheck() {
//        // ...
//        System.out.println("-----------------------");
//        System.out.println("Around before ");
//        logger.info("-----------------------");
//        logger.info("Around before ");
//    }
//    @Around("com.xyz.myapp.SystemArchitecture.businessService()")
//    @Around("pointCut()")
    @Around("pointThis()")
    public Object doBasicProfiling(ProceedingJoinPoint pjp) throws Throwable {
        // start stopwatch
        Object[] args = pjp.getArgs();
        for (Object arg : args) {
            logger.info("arg:" + arg);
        }
        logger.info("getKind:" + pjp.getKind() + ",getSignature：" + pjp.getSignature().toString() + "，getSourceLocation：" + pjp.getSourceLocation().toString() + "，getStaticPart：" + pjp.getStaticPart().toString() + "，getTarget：" + pjp.getTarget() + "，getThis：" + pjp.getThis());
        logger.info("-----------------------");
        logger.info("Around before ");
        Object retVal = pjp.proceed(args);
        // stop stopwatch
        logger.info("Around after：" + (retVal == null ? "" : retVal.toString()));
        logger.info("-----------------------");
        return retVal;
    }


}
